package com.simple.common.framework;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.simple.common.entity.ResData;
import com.simple.common.entity.po.sys.ChannelComp;
import com.simple.common.framework.context.Contexts;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * @author yasud
 * @date 2021年01月13日 15:32
 * @description
 */
@Slf4j
@Component
public class Reqer {

    @Autowired(required = false)
    LoadBalancerClient loadBalancerClient;

    @Autowired(required = false)
    RestTemplate restTemplate;

    private static Reqer _reqer;

    private static boolean logI = true;

    @Autowired
    public void init() {
        _reqer = this;
    }

    /**
     * 这里用rest方式最简单，
     * 内部接口相互通信全部使用post
     *
     * @param object
     * @param channel
     */
    @SneakyThrows
    public <R> ResData<R> forwardToChannel(Object object, ChannelComp channel, String controller, Class<R> responseClass) {
        ObjectMapper objectMapper = Contexts.OBJECTMAPPER;
        if (logI) log.info("请求渠道{}开始参数为{}", channel.getCode(), objectMapper.writeValueAsString(object));
        ServiceInstance instance = loadBalancerClient.choose(channel.getServiceProvider());
        Preconditions.checkNotNull(instance, "实例不存在,请检查数据配置，或者服务是否启动");
        ResData resData = Suppliers.memoize(() -> {
            try {
                ResponseEntity<String> responseEntity = restTemplate.postForEntity(getServiceUrl(instance, controller), object, String.class);
                ResData rResData = objectMapper.readValue(responseEntity.getBody(), ResData.class);
                return rResData;
            } catch (Exception ex) {
                ex.printStackTrace();
                return ResData.error(Throwables.getRootCause(ex).getMessage());
            }
        }).get();
        R r = objectMapper.readValue(objectMapper.writeValueAsString(resData.getData()), responseClass);
        resData.setData(r);
        if (logI) log.info("请求渠道{}结束返回{}", channel.getCode(), objectMapper.writeValueAsString(resData));
        return resData;
    }

    private String getServiceUrl(ServiceInstance instance, String type) {
        return "http://" + instance.getServiceId() + "/" + type;
    }

    /**
     * 当前对象
     *
     * @return
     */
    public static Reqer current(boolean log) {
        logI = log;
        Preconditions.checkNotNull(_reqer, "请求对象无效");
        Preconditions.checkNotNull(_reqer.loadBalancerClient, "依赖失败，请检查");
        Preconditions.checkNotNull(_reqer.restTemplate, "依赖失败请检查");
        return _reqer;
    }

    /**
     * 当前对象
     *
     * @return
     */
    public static Reqer current() {
        Preconditions.checkNotNull(_reqer, "请求对象无效");
        Preconditions.checkNotNull(_reqer.loadBalancerClient, "依赖失败，请检查");
        Preconditions.checkNotNull(_reqer.restTemplate, "依赖失败请检查");
        return _reqer;
    }
}

